Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GH-12] Added Ability to re-queue agenda Items. #89

Closed
wants to merge 6 commits into from

Conversation

sanjaydemansol
Copy link
Contributor

Fixes #12

Summary

  • Now old agenda items could be re-queued to upcoming meetings.

Testing notes

  • Create multiple agenda items for past date according to channel Hash Format.(You may create a message and edit its date manually)
  • open RHS menu on any of these and click Re-queue
    Screenshot_78
    Result:
    It will be requeued to upcoming meeting date.
    Screenshot_79

Ticket Link

#12

@codecov
Copy link

codecov bot commented Sep 17, 2021

Codecov Report

Base: 24.56% // Head: 22.31% // Decreases project coverage by -2.26% ⚠️

Coverage data is based on head (f4c0c33) compared to base (bc0e65d).
Patch coverage: 11.62% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #89      +/-   ##
==========================================
- Coverage   24.56%   22.31%   -2.26%     
==========================================
  Files           7        7              
  Lines         403      484      +81     
==========================================
+ Hits           99      108       +9     
- Misses        287      358      +71     
- Partials       17       18       +1     
Impacted Files Coverage Δ
server/command.go 0.00% <0.00%> (ø)
server/meeting.go 39.28% <28.57%> (-0.72%) ⬇️
server/utils.go 92.15% <80.00%> (-2.97%) ⬇️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

Copy link
Contributor

@maisnamrajusingh maisnamrajusingh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. @mickmister The PR has now been seperated from the ones related to #66

@hanzei hanzei added 2: Dev Review Requires review by a core committer 3: QA Review Requires review by a QA tester labels Sep 20, 2021
@dipak-demansol
Copy link

i will check this and update you after some time. @hanzei

@mickmister mickmister added this to the v0.3.0 milestone Oct 19, 2021
Copy link
Contributor

@mickmister mickmister left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @sanjaydemansol! This is a really valuable feature, it's great to see it completed.

I have some requests and questions, including a request to write unit tests

export function requeueItem(itemId) {
return async (dispatch, getState) => {
const command = `/agenda requeue ${itemId}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is itemId a post id? If so, it seems like having this requeue slash command doesn't make much sense. 1/5 we should implement this as an HTTP endpoint instead, using the server-side ServeHTTP hook.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mickmister we had a discussion for same at #88 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, the slash command makes sense then. Maybe we change this to /agenda requeue post ${postId}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copied over from #88 (comment):

Made /agenda requeue to support future options like
/agenda requeue all # meeting canceled, I want to requeue all items to next meeting.
/agenda requeue last # requeue last items
/agenda requeue last n # requeue last n items

webapp/src/actions/index.js Outdated Show resolved Hide resolved
webapp/src/index.js Outdated Show resolved Hide resolved
server/meeting_test.go Outdated Show resolved Hide resolved
Comment on lines +83 to +89
meetingDay := meetingDays[0]
for _, day := range meetingDays {
if todayWeekday <= day && day != dayToSkip {
meetingDay = day
break
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we write unit tests for this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

Message: fmt.Sprintf("#### %v %v) %v", hashtag, numQueueItems, originalPostMessage),
})
if appErr != nil {
return responsef("Error creating post: %s", appErr.Message)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error should be logged

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

messageRegexFormat = regexp.MustCompile(fmt.Sprintf(`(?m)^#### #%s(?P<date>.*) [0-9]+\) (?P<message>.*)?$`, prefix))
)

if matchGroups := messageRegexFormat.FindStringSubmatch(postToBeReQueued.Message); len(matchGroups) == 3 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to avoid this large indented block here

Suggested change
if matchGroups := messageRegexFormat.FindStringSubmatch(postToBeReQueued.Message); len(matchGroups) == 3 {
matchGroups := messageRegexFormat.FindStringSubmatch(postToBeReQueued.Message)
if len(matchGroups) != 3 {

Then return an error in that if block, and continue on otherwise

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great, done.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems that this is not done

originalPostMessage := strings.TrimSpace(matchGroups[2])

today := time.Now()
local, _ := time.LoadLocation("Local")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is Local what's used elsewhere in this plugin?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, should I remove it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is usually used instead, or is the only instance of LoadLocation?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sanjaydemansol Please see my question above:

What is usually used instead, or is the only instance of LoadLocation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No localized methods are used anywhere. removing LoadLocation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

time.LoadLocation is stored in local and is used here at.
formattedDate, _ := time.ParseInLocation(hashtagDateFormat, originalPostDate, local)


itemErr, numQueueItems := calculateQueItemNumber(args, p, hashtag)
if itemErr != nil {
return itemErr
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return itemErr
return errors.Wrap(itemErr, "failed to calculate queue item number")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our plugin doesn't support returning this as HTTP response.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the problem is that itemErr seems like it should be an error but it's a *model.CommandResponse. Maybe we can rename the variable commandResponse?

}
return responsef(fmt.Sprintf("Item has been Re-queued to %v", hashtag))
}
return responsef("Make sure, message is in required format!")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Under what circumstances would this occur? We definitely don't want to yell at the user 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced ! with . .It occurs if Hashtag is not correctly formatted.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0/5 it should be worded as

Please make sure the agenda hashtag is formatted properly.

@@ -19,6 +19,10 @@ export default class Plugin {
(channelId) => {
store.dispatch(openMeetingSettingsModal(channelId));
});

registry.registerPostDropdownMenuAction('Re-queue', (itemId) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

registerPostDropdownMenuAction supports a third argument, a callback that returns boolean representing if we should show this action in the post menu. We should use this callback as an opportunity to check if the post is an agenda item post. If we determine that it is not an agenda item post, we should return false in the callback.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We possibly want to use an identifier in post.props to signal that it's an agenda post. But that wouldn't work with manually created agenda items.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0/5, for now we could ensure we only show Re-queue option if a post starts with an #. Your thoughts? @mickmister thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0/5, for now we could ensure we only show Re-queue option if a post starts with an #

I think this is a little too broad of a claim. Two reasons come to mind:

  1. Posts can start with # because they are using a header, and not a hash tag. For example, # I'm a header renders as:

I'm a header

  1. Hashtags don't imply that it's an agenda hashtag.

I think we should go with the post.props strategy. If someone wants to use the post menu to re-queue an item they created manually, too bad. cc @hanzei

Another option going along with this same strategy is for the server-side of the plugin to apply the post.props mutation to the manually created agenda items during the MessageWillBePosted and MessageWillBeUpdated hooks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 for using post.props

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @mickmister @hanzei , nice approach.
Should I implement it in this PR or create a separate issue?

Copy link
Contributor

@mickmister mickmister Dec 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1/5 I'm thinking we should add it to this PR. @hanzei thoughts? I would want the change to block the release anyway

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sanjaydemansol Note that the PR should be using post.props to determine if the post is created by the plugin

@dipak-demansol
Copy link

@sanjaydemansol i found a issue but i was forgot to update here in PR, pls see this video.

vokoscreenNG-2021-10-18_23-35-10.1.mp4

.

@sanjaydemansol
Copy link
Contributor Author

sanjaydemansol commented Oct 25, 2021

@sanjaydemansol i found a issue but i was forgot to update here in PR, pls see this video.

vokoscreenNG-2021-10-18_23-35-10.1.mp4
.

Possibly its due to #78

- updates based on feedback
- bugfix for date allocation
Copy link

@dipak-demansol dipak-demansol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as discussed with Ben, we already have ticket for other issue as #78 so this PR is LGTM

@dipak-demansol dipak-demansol added QA Review Done PR has been approved by QA and removed 3: QA Review Requires review by a QA tester labels Nov 19, 2021
@mattermod
Copy link
Contributor

This PR has been automatically labelled "stale" because it hasn't had recent activity.
A core team member will check in on the status of the PR to help with questions.
Thank you for your contribution!

/cc @jasonblais @jfrerich @emilyacook

@hanzei
Copy link
Contributor

hanzei commented Dec 15, 2021

@sanjaydemansol Heads up that this branch has conflicts

@mattermod
Copy link
Contributor

The file .circleci/config.yml is in the blocklist for external contributors. Hence, these changes are not tested by the CI pipeline active until the build is re-triggered by a core committer or the PR is merged. Please be careful when reviewing it.
/cc @mattermost/core-security @mattermost/core-build-engineers

@mickmister
Copy link
Contributor

/update-branch

@mattermod
Copy link
Contributor

We don't have permissions to update this PR, please contact the submitter to apply the update.

@sanjaydemansol
Copy link
Contributor Author

Sure @sanjaydemansol. The changes in .circleci/config.yml are unrelated. Would you please revert them?

@hanzei reverted changes.

@hanzei hanzei dismissed their stale review February 10, 2022 12:22

Merge fixed

@hanzei
Copy link
Contributor

hanzei commented Feb 10, 2022

@mickmister Please take another look

@hanzei hanzei removed Do Not Merge/Awaiting PR Awaiting another pull request before merging (e.g. server changes) Lifecycle/1:stale labels Feb 10, 2022
Copy link
Contributor

@mickmister mickmister left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @sanjaydemansol, I have a few more requests

t.Errorf("nextWeekdayDateInWeekSkippingDay() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, &tt.want) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this also work?

Suggested change
if !reflect.DeepEqual(got, &tt.want) {
require.Equal(t, got, &tt.want) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mickmister tested code added require.Equal(t, got, &tt.want) {, not working. test cases failed.

}

var (
messageRegexFormat = regexp.MustCompile(fmt.Sprintf(`(?m)^#### #%s(?P<date>.*) [0-9]+\) (?P<message>.*)?$`, prefix))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use regexp.Compile instead of MustCompile so we can handle the error and avoid a panic. As well as anywhere else we are calling MustCompile inside of a function.

Comment on lines +49 to +51
var patch, err = mpatch.PatchMethod(time.Now, func() time.Time {
return time.Date(2021, 11, 15, 00, 00, 00, 0, time.UTC)
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking we would pass in the value for now in the function we're testing this with, rather than implicitly patching the value here. @sanjaydemansol What do you think?

We would modify nextWeekdayDateInWeekSkippingDay to accept now as a parameter:

now, _ := time.Date(2021, 11, 15, 00, 00, 00, 0, time.UTC)

got, err := nextWeekdayDateInWeekSkippingDay(now, tt.args.meetingDays, tt.args.nextWeek, tt.args.dayToSkip)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use now for past and future cases hence, we should be fine with patching.

Comment on lines 212 to 215
postToBeReQueued, er := p.API.GetPost(oldPostID)
if er != nil {
return responsef("Error fetching post.")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0/5 We should log this error

Suggested change
postToBeReQueued, er := p.API.GetPost(oldPostID)
if er != nil {
return responsef("Error fetching post.")
}
postToBeReQueued, appErr := p.API.GetPost(oldPostID)
if appErr != nil {
return responsef("Error fetching post.")
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added Logs for error.

originalPostMessage := strings.TrimSpace(matchGroups[2])

today := time.Now()
local, _ := time.LoadLocation("Local")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sanjaydemansol Please see my question above:

What is usually used instead, or is the only instance of LoadLocation?


itemErr, numQueueItems := calculateQueItemNumber(args, p, hashtag)
if itemErr != nil {
return itemErr
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the problem is that itemErr seems like it should be an error but it's a *model.CommandResponse. Maybe we can rename the variable commandResponse?

messageRegexFormat = regexp.MustCompile(fmt.Sprintf(`(?m)^#### #%s(?P<date>.*) [0-9]+\) (?P<message>.*)?$`, prefix))
)

if matchGroups := messageRegexFormat.FindStringSubmatch(postToBeReQueued.Message); len(matchGroups) == 3 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems that this is not done

export function requeueItem(postId) {
return async (dispatch, getState) => {
const command = `/agenda requeue ${postId}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we plan to support other commands in the future like this, I propose we be specific here that we are passing a post id #89 (comment)

Suggested change
const command = `/agenda requeue ${postId}`;
const command = `/agenda requeue post ${postId}`;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mickmister Updated code as per feedback

return nil, numQueueItems + 1
}

func (p *Plugin) executeCommandReQueue(args *model.CommandArgs) *model.CommandResponse {
Copy link
Contributor

@mickmister mickmister Feb 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like this function was refactored, but we agreed it should be refactored and tested in this conversation

@jfrerich jfrerich removed their request for review February 10, 2022 18:19
@sanjaydemansol
Copy link
Contributor Author


image

@mickmister Using Compile in place of MustCompile causes linting issues.

@mickmister
Copy link
Contributor

@sanjaydemansol Unrelated to the error message you've posted, but we shouldn't be using the appErr variable name for regular errors, as opposed to *model.AppError.

Is it possible for this regex to be defined on the package level, outside of the function? Then we can use MustCompile

@sanjaydemansol
Copy link
Contributor Author

https://github.com/mattermost/mattermost-plugin-agenda/blob/9457541a516a46efab8b9247dd4822b8688ec3ef/server/meeting.go#L14-L18

@mickmister I think regex is already defined on the package level, outside of the function.

@mickmister
Copy link
Contributor

@sanjaydemansol We should follow this convention:

If the regex compilation requires a value at runtime, the compilation needs to occur in a function, so we should use Compile to avoid a panic at runtime.

If the regex compilation does not require a value at runtime, the compilation should occur on the package level, and we should use MustCompile.

@sanjaydemansol
Copy link
Contributor Author

@mickmister updated code as per your suggestion. used MustCompile at package level.

@mattermod
Copy link
Contributor

This PR has been automatically labelled "stale" because it hasn't had recent activity.
A core team member will check in on the status of the PR to help with questions.
Thank you for your contribution!

/cc @aspleenic

@hanzei hanzei removed the QA Review Done PR has been approved by QA label Mar 5, 2022
@maisnamrajusingh maisnamrajusingh self-assigned this Mar 24, 2022
@mattermod
Copy link
Contributor

This PR has been automatically labelled "stale" because it hasn't had recent activity.
A core team member will check in on the status of the PR to help with questions.
Thank you for your contribution!

@@ -19,6 +19,10 @@ export default class Plugin {
(channelId) => {
store.dispatch(openMeetingSettingsModal(channelId));
});

registry.registerPostDropdownMenuAction('Re-queue', (postId) => {
store.dispatch(requeueItem(postId));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to use post.props to:

  • declare a given post was made with the agenda plugin
  • and check here to see if we should render the Re-queue item in the post dropdown menu

@hanzei hanzei added Lifecycle/3:orphaned and removed 2: Dev Review Requires review by a core committer Awaiting Submitter Action Blocked on the author Lifecycle/1:stale labels Feb 21, 2023
@hanzei hanzei closed this Feb 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Re-queue an item for next meeting
7 participants